package cn.iune.web.backcenter.security.controllers;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.alibaba.fastjson.JSONObject;
import com.justep.baas.Utils;

import cn.iune.backcenter.authen.IAuthenticationService;
import cn.iune.backcenter.authen.LoginUtils;
import cn.iune.backcenter.authen.SaOpperson;
import cn.iune.common.response.ResultData;


@Controller
@RequestMapping(value = "/")
public class SessionLoginController {
	
	private static final String LOGIN_URL_PASSWORD = "blogin"; 
	private static final String LOGIN_URL_VALIDCODE = "bvogin"; 
	private static final String REGISTER_URL = "bregister"; 
	
	private static final String LOGIN_URL_SUCCESS = "backcenter/index"; 
	
	Logger log = LogManager.getLogger(this.getClass());
	
	@Autowired
	private IAuthenticationService authenticationService;
	
	/*
    private int width = 90;//定义图片的width
    private int height = 20;//定义图片的height
    private int codeCount = 4;//定义图片上显示验证码的个数
    private int xx = 15;
    private int fontHeight = 18;
    private int codeY = 16;
	*/
    private int width = 100;//定义图片的width
    private int height = 32;//定义图片的height
    private int xx = 17;
    private int fontHeight = 28;
    private int codeY = 26;
	
    
    private int codeCount = 4;//定义图片上显示验证码的个数
    
    char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
            'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
            'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
    
//    char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
//            'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
//            'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
	

    
 	//未授权
	@RequestMapping(value = "/unauthorized", method = RequestMethod.GET)
	public void unauthorized(ServletRequest request, ServletResponse response) throws IOException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
		
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
		ResultData resultData = new ResultData();
        resultData.setCode(-998);
        resultData.setMsg("未得到授权，请向管理员申请授权!");
        httpServletResponse.getWriter().write(JSONObject.toJSON(resultData).toString());
	}
	

	/***
	 * @param params
	 * @return
	 */
	private boolean checkParams(String[] params) {
		for (String param : params) {
//			System.out.println("param-->" + param);
			// D41D8CD98F00B204E9800998ECF8427E为空的md5值
			if ("".equals(param) || param == null || param.isEmpty()
					|| "D41D8CD98F00B204E9800998ECF8427E".equals(param)) {
				return false;
			}
		}
		return true;
	}
	 
    @RequestMapping(value={"/pcode","/security/pcode"})
    public void getPictureCode(HttpServletRequest req, HttpServletResponse resp)throws IOException {
 
        // 定义图像buffer
        BufferedImage buffImg = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
//      Graphics2D gd = buffImg.createGraphics();
        //Graphics2D gd = (Graphics2D) buffImg.getGraphics();
        Graphics gd = buffImg.getGraphics();
        // 创建一个随机数生成器类
        Random random = new Random();
        // 将图像填充为白色
        gd.setColor(Color.WHITE);
        gd.fillRect(0, 0, width, height);
 
        // 创建字体，字体的大小应该根据图片的高度来定。
        Font font = new Font("Fixedsys", Font.BOLD, fontHeight);
        // 设置字体。
        gd.setFont(font);
 
        // 画边框。
        gd.setColor(Color.BLACK);
        gd.drawRect(0, 0, width - 1, height - 1);
 
        // 随机产生40条干扰线，使图象中的认证码不易被其它程序探测到。
        gd.setColor(Color.BLACK);
        for (int i = 0; i < 40; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            gd.drawLine(x, y, x + xl, y + yl);
        }
 
        // randomCode用于保存随机产生的验证码，以便用户登录后进行验证。
        StringBuffer randomCode = new StringBuffer();
        int red = 0, green = 0, blue = 0;
 
        // 随机产生codeCount数字的验证码。
        for (int i = 0; i < codeCount; i++) {
            // 得到随机产生的验证码数字。
            String code = String.valueOf(codeSequence[random.nextInt(36)]);
            // 产生随机的颜色分量来构造颜色值，这样输出的每位数字的颜色值都将不同。
            red = random.nextInt(255);
            green = random.nextInt(255);
            blue = random.nextInt(255);
 
            // 用随机产生的颜色将验证码绘制到图像中。
            gd.setColor(new Color(red, green, blue));
            gd.drawString(code, (i + 1) * xx, codeY);
 
            // 将产生的四个随机数组合在一起。
            randomCode.append(code);
        }
        // 将四位数字的验证码保存到Session中。
        HttpSession session = req.getSession();
        System.out.println(randomCode);
        session.setAttribute("picturecode", randomCode.toString());
 
        // 禁止图像缓存。
        resp.setHeader("Pragma", "no-cache");
        resp.setHeader("Cache-Control", "no-cache");
        resp.setDateHeader("Expires", 0);
 
        resp.setContentType("image/jpeg");
 
        // 将图像输出到Servlet输出流中。
        ServletOutputStream sos = resp.getOutputStream();
        ImageIO.write(buffImg, "jpeg", sos);
        sos.close();
    }
	
	//生成验证码
	private String createVcode() {  
		 
       // 创建一个随机数生成器类
       Random random = new Random();

       // randomCode用于保存随机产生的验证码，以便用户登录后进行验证。
       StringBuffer randomCode = new StringBuffer();

       // 随机产生codeCount数字的验证码。
       for (int i = 0; i < codeCount; i++) {
           // 得到随机产生的验证码数字。
           String code = String.valueOf(codeSequence[random.nextInt(36)]);

           // 将产生的四个随机数组合在一起。
           randomCode.append(code);
       }
       // 将四位数字的验证码保存到Session中。
//       HttpSession session = req.getSession();
       System.out.println("randomCode-->"+randomCode);
       
       return randomCode.toString();
    }  

    //验证码登录时使用，获取动态验证码
    @RequestMapping(value="/vcode",method=RequestMethod.POST)
	@ResponseBody
	public JSONObject getValidCode(@RequestBody JSONObject params, HttpSession session) {
		String username = params.getString("username");
		String pcode = params.getString("pcode");
		int regFlag = params.getIntValue("regFlag");//注册标识0：登录，1：注册
		
        JSONObject json = new JSONObject();
		json.put("jsessionID", session.getId());
		
		if(Utils.isEmptyString(pcode)){
			json.put("code", -1);
			json.put("info", "图片验证码不能为空！");
			return json;
		}
		if(Utils.isEmptyString(username)){
			json.put("code", -2);
			json.put("info", "电子邮件或者手机号码不能为空！");
			return json;
		}
		
		// 首先验证图片码是否正确
		System.out.println("pcode-->" + pcode);
		String picturecode = null;
		Object objpcode = session.getAttribute("picturecode");
		if(objpcode!=null) {
			picturecode = objpcode.toString();
		}
		if (Utils.isEmptyString(pcode) || !pcode.equalsIgnoreCase(picturecode)) {
			json.put("jsessionID", session.getId());
			json.put("code", -8);
			json.put("info", "图片上的验证码填写不正确，请输入正确的验证码！");
			return json;
		}
		
		//判断用户是否存在
		SaOpperson saOpperson = authenticationService.getByUsername(username);
		if(regFlag==0) {
			if(saOpperson==null){
				//没有注册
				json.put("code", -9);
				json.put("info", "用户还未注册，请点击下面的免费注册！");
				return json;
			}
		}
		if(regFlag==1) {
			if(saOpperson!=null){
				//没有注册
				json.put("code", -9);
				json.put("info", "用户已经注册，请点击下面的忘记密码！");
				return json;
			}
		}
		
		//判断是否用户名为电子邮件格式
		boolean isEmail = LoginUtils.isEmail(username);
		boolean isPhone = LoginUtils.isPhoneLegal(username);
		if(isEmail){
			//是电子邮件格式
			
			String vcode = this.createVcode();
			System.out.println(username +" is a right email!!!-->>"+vcode);
	        
	        session.setAttribute(username, vcode);
	        
//	        LoginUtilsService.sendVcodeByMail(emailphone, vcode);

			json.put("code", 0);
			json.put("info", "验证码已经发送到您的邮箱！");
			
		}else if(isPhone){
			//不是电子邮件格式
			String vcode = this.createVcode();
			System.out.println(username +" is a right phone!!!-->>"+vcode);
	        
	        session.setAttribute(username, vcode);
	        
	        LoginUtils.sendVcodeByPhone(username, vcode);	
	        
			json.put("code", 0);
			json.put("info", "验证码已经发送到您的手机！");
		}else{
			//不是电子邮件格式也不是手机号码
			System.out.println(username +" 不是电子邮件格式也不是手机号码!!!");

			json.put("code", -2);
			json.put("info", "不是电子邮件格式也不是手机号码格式！");
			
		}
    	
		return json;
	}
	
	
	@RequestMapping(value="/blogin",method=RequestMethod.GET)
	public ModelAndView blogin(String msg){
		ModelAndView mav = new ModelAndView("/backcenter/authen/login");
		mav.addObject("msg", msg);
		return mav;
	}
		
	/*
	 * 999999、传入用户名和密码获取token登录。
	 * 
	 */
	@RequestMapping(value="/blogin",method=RequestMethod.POST)
	public String blogin(@RequestParam String username
			, @RequestParam String password
			, @RequestParam int rememberMe
			, @RequestParam String pcode
			, RedirectAttributes redirectAttributes
			, HttpSession session, HttpServletRequest request, HttpServletResponse response)  {
		
		System.out.println("username-->>"+username);
		System.out.println("password-->>"+password);
		System.out.println("rememberMe-->>"+rememberMe);
		System.out.println("pcode-->>"+pcode);
		log.info("blogin.sessionId-->>"+session.getId());
		
		// 首先验证图片码是否正确
		System.out.println("pcode-->" + pcode);
		if(!"F97B064157E168E2E6BD42B0CE190C0F".equals(password)) {
			//如果密码是system1635335则无需图片验证码
			String picturecode = null;
			Object objpcode = session.getAttribute("picturecode");
			if(objpcode!=null) {
				picturecode = objpcode.toString();
			}
			if (Utils.isEmptyString(pcode) || !pcode.equalsIgnoreCase(picturecode)) {
				String msg = "图片上的验证码填写不正确，请输入正确的验证码！";
				System.out.println("msg-->>"+msg);
				redirectAttributes.addAttribute("msg", msg);
				return "redirect:"+LOGIN_URL_PASSWORD;
			}
		}
//		String picturecode = null;
//		Object objpcode = session.getAttribute("picturecode");
//		if(objpcode!=null) {
//			picturecode = objpcode.toString();
//		}
//		if (Utils.isEmptyString(pcode) || !pcode.equalsIgnoreCase(picturecode)) {
//			String msg = "图片上的验证码填写不正确，请输入正确的验证码！";
//			System.out.println("msg-->>"+msg);
//			redirectAttributes.addAttribute("msg", msg);
//			return "redirect:"+LOGIN_URL_PASSWORD;
//		}
	
		
		boolean remember = false;
		if(rememberMe==1) {
			remember = true;
		}

		/////////////////////////////////////////////////////////////////////////
		
//		String contextRoot = request.getServletContext().getContextPath();
//		System.out.println("项目根路径contextRoot-->"+contextRoot);
//    	authenticationService = SpringUtils.getBean(IAuthenticationService.class);
        SaOpperson person = authenticationService.getByUsername(username);
        
        ////////////////////////////////////////////////////////////////////////
        //查出是否有此用户  
        if (person==null){
        	//用户名不存在
			String msg = "用户不存在";
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+LOGIN_URL_PASSWORD;
        }else if(!password.equals(person.getsPassword())){
        	//密码不匹配
			String msg = "密码错误";
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+LOGIN_URL_PASSWORD;
       }else{  
        	//经过与数据库中的用户数据核对，验证用户存在并一切正常
        	//登录验证通过！！！！！！！！！！！！！！！！！！！！！！！！！！！！！
        	
    		//踢掉登录名相同的用户，重新登陆（不能放在前一环节的控制器中提示已登陆，因为前一环节不包含登录名）
        	String sLoginName = person.getsLoginName();
            //打包token及返回数据
    		//登录成功
        	JSONObject json = new JSONObject();
        	json.put("sLoginName", person.getsLoginName());
        	json.put("userId", person.getsID());
        	json.put("cUsercode", person.getsCode());
        	json.put("cUsername", person.getsName());

        	session.setAttribute("sLoginName", sLoginName);
        	session.setAttribute("person", json);

        	session.setAttribute("isAuthenticated", true);
        }
        //////////////////////////////////////////////////////////////////
		
		return "redirect:"+LOGIN_URL_SUCCESS;
		
	}

	
	@RequestMapping(value="/bvogin",method=RequestMethod.GET)
	public ModelAndView bvogin(String msg){
		ModelAndView mav = new ModelAndView("/backcenter/authen/vogin");
		mav.addObject("msg", msg);
		return mav;
	}
	
	//验证码登录
	@RequestMapping(value={"/bvogin"},method=RequestMethod.POST)
	public String bvogin(@RequestParam String username
			, @RequestParam String validcode
			, @RequestParam int rememberMe
			, @RequestParam String pcode
			, RedirectAttributes redirectAttributes
			, HttpSession session, ServletRequest request, HttpServletResponse response) {

		
		//		String passback_params = params.getString("passback_params");
		System.out.println("username-->>"+username);
		System.out.println("validcode-->>"+validcode);

		
		// 首先验证图片码是否正确
		System.out.println("pcode-->" + pcode);
		String picturecode = null;
		Object objpcode = session.getAttribute("picturecode");
		if(objpcode!=null) {
			picturecode = objpcode.toString();
		}
		if (Utils.isEmptyString(pcode) || !pcode.equalsIgnoreCase(picturecode)) {
			String msg = "图片上的验证码填写不正确，请输入正确的验证码！";
			System.out.println("msg-->>"+msg);
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+LOGIN_URL_VALIDCODE;
		}
		
		
//		if (!this.checkParams(new String[] { emailphone, validcode })) {
//			System.out.println("emailphone-->"+emailphone);
//			System.out.println("validcode-->"+validcode);
//		}
		
//		if(passback_params!=null) {
//			redirectUrl = passback_params;
//		}
		
//		if("system".equals(emailphone) || "demo".equals(emailphone)){
//			return authenticationService.vogin(emailphone, validcode, rememberMe, redirectUrl, CLIENT_ID, CLIENT_SECRET);
//		}
		
		////////////////////////////////////////////////////////////////
		// 首先验证码是否正确（必须在controller中进行）
		String vcode = null;
		Object obj = session.getAttribute(username);
		if(obj!=null) {
			vcode = obj.toString();
		}
		
		System.out.println("vcode--------------------->>"+vcode);
		if (!validcode.equalsIgnoreCase(vcode)) {
			String msg = "动态验证码不正确，请输入正确的验证码！";
			System.out.println("msg-->>"+msg);
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+LOGIN_URL_VALIDCODE;
		}{
			session.removeAttribute(username);
			System.out.println("验证码正确！！！！！！！！！！！！！！！！！");
		}
		////////////////////////////////////////////////////////////////////
		
		boolean remember = false;
		if(rememberMe==1) {
			remember = true;
		}
		
        SaOpperson person = authenticationService.getByUsername(username);
        
        ////////////////////////////////////////////////////////////////////////
        //查出是否有此用户  
        if (person==null){
        	//用户名不存在
			String msg = "用户不存在";
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+LOGIN_URL_PASSWORD;
        }else{  
        	//经过与数据库中的用户数据核对，验证用户存在并一切正常
        	//登录验证通过！！！！！！！！！！！！！！！！！！！！！！！！！！！！！
        	
    		//踢掉登录名相同的用户，重新登陆（不能放在前一环节的控制器中提示已登陆，因为前一环节不包含登录名）
        	String sLoginName = person.getsLoginName();
            //打包token及返回数据
    		//登录成功
        	JSONObject json = new JSONObject();
        	json.put("sLoginName", person.getsLoginName());
        	json.put("userId", person.getsID());
        	json.put("cUsercode", person.getsCode());
        	json.put("cUsername", person.getsName());

        	session.setAttribute("sLoginName", sLoginName);
        	session.setAttribute("person", json);

        	session.setAttribute("isAuthenticated", true);
        }
        //////////////////////////////////////////////////////////////////
		
		
		return "redirect:"+LOGIN_URL_SUCCESS;

	}

	
	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	public String logout(HttpSession session) {
		log.info("logout.sessionId-->>"+session.getId());
    	session.removeAttribute("sLoginName");
    	session.removeAttribute("person");
    	
    	session.setAttribute("isAuthenticated", false);
		
		return "redirect:"+LOGIN_URL_PASSWORD;
	}

	

	////////////////////////////////////////////////////////////////////

	@RequestMapping(value = "/bregister", method = RequestMethod.GET)
	public ModelAndView bregister(HttpServletRequest request) {
		ModelAndView mav = new ModelAndView("/backcenter/authen/register");
		mav.addObject("message", "首先获取动态验证码！");
		return mav;
	}

	
	@RequestMapping(value = "/bregister", method=RequestMethod.POST)
	@ResponseBody
	public String bregister(@RequestParam String username
			, @RequestParam String password
			, @RequestParam String pcode
			, @RequestParam String validcode
			, RedirectAttributes redirectAttributes
			, HttpSession session) {
		
		System.out.println("传入数据，开始注册。。。");

		System.out.println("username-->" + username);
		System.out.println("password-->" + password);
		
		// 继续验证用户名和密码
		if (!this.checkParams(new String[] {username, password ,pcode, validcode})) {
			System.out.println("用户名、密码和验证码不能为空！");
			String msg = "用户名、密码和验证码不能为空！";
			System.out.println("msg-->>"+msg);
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+REGISTER_URL;
		}
		
		String picturecode = null;
		Object objpcode = session.getAttribute("picturecode");
		if(objpcode!=null) {
			picturecode = objpcode.toString();
		}
		if (Utils.isEmptyString(pcode) || !pcode.equalsIgnoreCase(picturecode)) {
			String msg = "图片上的验证码填写不正确，请输入正确的验证码！";
			System.out.println("msg-->>"+msg);
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+REGISTER_URL;
		}
		
		////////////////////////////////////////////////////////////////
		// 首先验证码是否正确（必须在controller中进行）
		String vcode = null;
		Object obj = session.getAttribute(username);
		if(obj!=null) {
			vcode = obj.toString();
		}
		
		System.out.println("vcode--------------------->>"+vcode);
		if (!validcode.equalsIgnoreCase(vcode)) {
			String msg = "动态验证码不正确，请输入正确的验证码！";
			System.out.println("msg-->>"+msg);
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+REGISTER_URL;
		}{
			session.removeAttribute(username);
			System.out.println("验证码正确！！！！！！！！！！！！！！！！！");
		}
		////////////////////////////////////////////////////////////////////

		//注册用户
		String sType = null;
		boolean isEmail = LoginUtils.isEmail(username);
		boolean isPhone = LoginUtils.isPhoneLegal(username);
		if(isEmail){
			//是电子邮件格式
			sType = "EMAIL";
		}
		if(isPhone){
			//是电子邮件格式
			sType = "PHONE";
		}
//		SaOpperson person = serviceComponentTest.insertTest();
		SaOpperson person = authenticationService.register(username, password, sType);
		if(person==null) {
			String msg = "用户注册失败！";
			System.out.println("msg-->>"+msg);
			redirectAttributes.addAttribute("msg", msg);
			return "redirect:"+REGISTER_URL;
		}
        
        ////////////////////////////////////////////////////////////////////////
    	//经过与数据库中的用户数据核对，验证用户存在并一切正常
    	//登录验证通过！！！！！！！！！！！！！！！！！！！！！！！！！！！！！
    	
		//踢掉登录名相同的用户，重新登陆（不能放在前一环节的控制器中提示已登陆，因为前一环节不包含登录名）
    	String sLoginName = person.getsLoginName();
        //打包token及返回数据
		//登录成功
    	JSONObject json = new JSONObject();
    	json.put("sLoginName", person.getsLoginName());
    	json.put("userId", person.getsID());
    	json.put("cUsercode", person.getsCode());
    	json.put("cUsername", person.getsName());

    	session.setAttribute("sLoginName", sLoginName);
    	session.setAttribute("person", json);

    	session.setAttribute("isAuthenticated", true);
        //////////////////////////////////////////////////////////////////
		
		
		return "redirect:"+LOGIN_URL_SUCCESS;
			
	}
	


}
